1 : <?php
2 : /*--------------------------------------------------------------------------+
3 : This file is part of eStudy.
4 : planspiel/classes/class.planspiel.inc.php
5 : - Modulgruppe: Planspiel
6 : - Beschreibung: Erstellen eines Planspiel-Objektes mit entsprechenden Funktionen.
7 : - Version: 0.8, 02/03/07
8 : - Autor(en): Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
9 : +---------------------------------------------------------------------------+
10 : This program is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU General Public License
12 : as published by the Free Software Foundation; either version 2
13 : of the License, or any later version.
14 : +---------------------------------------------------------------------------+
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 : +--------------------------------------------------------------------------*/
23 : /**
24 : * Erstellen eines Planspiel-Objektes mit entsprechenden Funktionen.
25 : * @package eStudy.Planspiel
26 : * @version 0.8, 02/03/07
27 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
28 : */
29 : require_once (PATH_TO_ROOT."common/classes/class.bbcode.inc.php");
30 : require_once (PATH_TO_ROOT."common/classes/class.formular.inc.php");
31 : require_once (PATH_TO_ROOT."courses/classes/class.Course.inc.php");
32 : require_once (PATH_TO_ROOT."roleplay/classes/class.userrolemanagement.inc.php");
33 : require_once (PATH_TO_ROOT."teams/classes/class.userteammanagement.inc.php");
34 : require_once (PATH_TO_ROOT."ressourcen/classes/class.insert.inc.php");
35 : require_once (PATH_TO_ROOT."planspiel/classes/class.phase.inc.php");
36 : require_once (PATH_TO_ROOT."planspiel/classes/class.color_indicator.inc.php");
37 : require_once (PATH_TO_ROOT."planspiel/classes/class.PlanspielBudget.inc.php");
38 :
39 : class Planspiel {
40 : /**
41 : * ID des Planspiels
42 : * @var int
43 : * @access private
44 : */
45 : var $ID;
46 : /**
47 : * ID des Kurses, in dem sich das Planspiel befindet
48 : * @var int
49 : * @access private
50 : */
51 : var $courseID;
52 : /**
53 : * User-ID des Spielleiters
54 : * @var int
55 : * @access private
56 : */
57 : var $leaderID;
58 : /**
59 : * ID des Verzeichnisses, das die Vorlagen für Dokumente enthält
60 : * @var int
61 : * @access private
62 : */
63 : var $templateFolder;
64 : /**
65 : * Name des Planspiels
66 : * @var string
67 : * @access private
68 : */
69 : var $name;
70 : /**
71 : * Beschreibung des Planspiels
72 : * @var string
73 : * @access private
74 : */
75 : var $description;
76 : /**
77 : * Phasen-Objekte des Planspiels
78 : * @var array
79 : * @access private
80 : */
81 : var $phases;
82 : /**
83 : * ID des zum Planspiel gehörenden Ressourcen-Ordners.
84 : * @var int
85 : * @access private
86 : */
87 : var $folderID;
88 : /**
89 : * ID des zum Planspiel gehörenden Boards.
90 : * @var int
91 : * @access private
92 : */
93 : var $boardID;
94 : /**
95 : * ID der zum Planspiel gehörenden Map.
96 : * @var int
97 : * @access private
98 : */
99 : var $mapID;
100 : /**
101 : * Gibt an, ob das Planspiel abgeschlossen ist.
102 : * @var bool
103 : * @access private
104 : */
105 : var $isFinished;
106 : /**
107 : * Gibt an, wann das Planspiel begonnen wurde.
108 : * @var int
109 : * @access private
110 : */
111 : var $in_progress;
112 : /**
113 : * Gibt an, wann das Planspiel abgeschlossen sein sollte.
114 : * @var bool
115 : * @access private
116 : */
117 : var $deadline;
118 : /**
119 : * Object von PlanspielBudget zur Berechnung des Budgets inclusive der Aufwände für Reviews usw.
120 : * @var PlanspielBudget
121 : * @access private
122 : */
123 : private $planspielBudget;
124 :
125 : /**
126 : * Konstruktor
127 : * Liest die Daten des Planspiels aus, dessen ID übergeben wurde
128 : * oder erzeugt ein neues Planspiel-Objekt mit der ID 0.
129 : *
130 : * @access public
131 : * @param int $ID ID des Planspiels oder 0 für neues Planspiel
132 : */
133 : function Planspiel($ID) {
134 0 : global $db, $settings;
135 0 : $dbp = $settings["dbPrefix"];
136 0 : if (strval(intval($ID)) == $ID && $ID > 0) {
137 0 : $this->ID = intval($ID);
138 0 : $result = $db->get_row("SELECT * FROM {$dbp}planspiel WHERE id='$ID'");
139 0 : if ($db->num_rows) {
140 0 : $this->courseID = intval($result->course_id);
141 0 : $this->leaderID = intval($result->leader);
142 0 : $this->templateFolder = intval($result->template_folder);
143 0 : $this->name = $result->name;
144 0 : $this->description = $result->description;
145 0 : $this->folderID = intval($result->folder_id);
146 0 : $this->boardID = intval($result->board_id);
147 0 : $this->isFinished = (bool)$result->finished;
148 0 : $this->deadline = $result->deadline;
149 0 : $this->in_progress = $result->in_progress;
150 0 : } else {
151 0 : $this->setDefaultValues();
152 : }
153 0 : } else {
154 0 : $this->setDefaultValues();
155 : }
156 0 : }
157 : /**
158 : * Setzt die Standardwerte für ein neues Planspiel-Objekt.
159 : *
160 : * @access private
161 : * @return void
162 : */
163 : function setDefaultValues() {
164 0 : $this->ID = 0;
165 0 : $this->courseID = $_SESSION["course"];
166 0 : $this->leader = "";
167 0 : $this->leaderID = 0;
168 0 : $this->templateFolder = 0;
169 0 : $this->name = "";
170 0 : $this->description = "";
171 0 : $this->folderID = 0;
172 0 : $this->boardID = 0;
173 0 : $this->isFinished = false;
174 0 : $this->deadline = 0;
175 0 : $this->in_progress = 0;
176 0 : }
177 : /**
178 : * Zeigt das Formular zum Bearbeiten des Planspiels an.
179 : *
180 : * @access public
181 : * @return void
182 : */
183 : function showEditForm() {
184 0 : global $db, $settings;
185 0 : $dbp = $settings["dbPrefix"];
186 0 : $ID = $this->ID;
187 0 : $form = new Formular();
188 0 : $form->setTemplate("<table class='contentTable'>", "<tr valign='top'><td>", "<td>");
189 0 : $form->setButtons(1, "Speichern");
190 0 : $form->addRawCode("<tr><td colspan='2' class='tableHead'>".($this->ID > 0 ? "Planspiel bearbeiten" : "Neues Planspiel") ."</td></tr>");
191 0 : $form->addInput("hidden", "ID", "", 0, $this->ID);
192 0 : $form->addInput("text", "name", "Name", 60, $this->name, 100);
193 0 : $form->addTextArea("description", "Beschreibung<br />(".BBCode::getTagOverviewLink() .")", 60, 10, $this->description);
194 0 : $participants = Course::getParticipants($this->courseID, "all", "user.Nachname, user.Vorname");
195 0 : $user = array();
196 0 : foreach($participants as $participant) {
197 0 : $user[] = array(Data::toHTML($participant->lastname.", ".$participant->firstname, false), $participant->userid);
198 0 : }
199 0 : $form->addSelect("leader", "Spielleiter", $user, 1, false, ($this->leaderID > 0 ? $this->leaderID : ""));
200 0 : $filem = new Insert();
201 0 : $folders = array();
202 0 : $count = $filem->printSubFolder(0, "", $folders, 0, "");
203 0 : $form->addSelect("folder", "Template-Ordner", $folders, ($count > 10 ? 10 : $count), false, ($this->templateFolder > 0 ? $this->templateFolder : ""));
204 0 : if ($this->ID == 0) {
205 0 : $form->addToNextTag("id='createfolder'");
206 0 : $form->addInput("checkbox", "createfolder", "<label for='createfolder'>Gleichnamigen Ressourcen-Ordner erstellen</label>", 60, 1, 1);
207 0 : $form->addToNextTag("id='createboard'");
208 0 : $form->addInput("checkbox", "createboard", "<label for='createboard'>Gleichnamiges Board erstellen</label>", 60, 1, 1);
209 0 : $form->addMarker();
210 0 : echo $form->getForm(0);
211 0 : echo "<tr valign='top'><td>Start des Planspiels</td><td>";
212 0 : $date = getdate(time());
213 0 : $ds = new DateSelection($date["mday"], $date["mon"], $date["year"], $date["hours"], $date["minutes"]);
214 0 : $ds->clearStrings();
215 0 : $ds->printCalender("inProgress", "all");
216 0 : echo "</td></tr>";
217 0 : $form->addMarker();
218 0 : echo $form->getForm(1);
219 0 : echo "<tr valign='top'><td>Deadline</td><td>";
220 0 : $date = getdate(time()+24*3600);
221 0 : $ds = new DateSelection($date["mday"], $date["mon"], $date["year"], $date["hours"], $date["minutes"]);
222 0 : $ds->clearStrings();
223 0 : $ds->printCalender("deadline", "all");
224 0 : echo "</td></tr>";
225 0 : } else {
226 0 : $form->addToNextTag("id='finished'");
227 0 : $form->addInput("checkbox", "finished", "<label for='finished'>Planspiel abgeschlossen</label>", 60, 1, (int)$this->isFinished);
228 0 : $form->addMarker();
229 0 : echo $form->getForm(0);
230 0 : if($this->in_progress == 0){
231 0 : echo "<tr valign='top'><td>Start des Planspiels</td><td>";
232 0 : $date = getdate(time());
233 0 : $ds = new DateSelection($date["mday"], $date["mon"], $date["year"], $date["hours"], $date["minutes"]);
234 0 : $ds->clearStrings();
235 0 : $ds->printCalender("inProgress", "all");
236 0 : echo "</td></tr>";
237 0 : } else {
238 0 : $form->addRawCode("<tr><td>Bearbeitung</td><td>"."Dieses Planspiel wurde am ".date("d.m.Y", $this->in_progress)." um ".date("H:i", $this->in_progress)." freigegeben."."</td></tr>");
239 : }
240 0 : echo "<tr valign='top'><td>Deadline</td><td>";
241 0 : $date = getdate($this->deadline);
242 0 : $ds = new DateSelection($date["mday"], $date["mon"], $date["year"], $date["hours"], $date["minutes"]);
243 0 : $ds->clearStrings();
244 0 : $ds->printCalender("deadline", "all");
245 0 : echo "</td></tr>";
246 : }
247 0 : $form->addButtons();
248 0 : if($this->ID == 0)
249 0 : echo $form->getForm(2);
250 : else
251 0 : echo $form->getForm(1);
252 0 : }
253 : /**
254 : * Versucht, die im übergebenen Array vorhandenen Daten anhand der
255 : * assoziativen Array-Indizes als neue Planspiel-Daten abzuspeichern. Dabei
256 : * kann es sich zum Beispiel um das $_POST-Array handeln. Es werden dabei
257 : * entweder alle oder keine Daten gespeichert. Sind einige der Daten
258 : * fehlerhaft, wird ein String mit Fehlermeldungen zurückgeliefert, sonst
259 : * der boolsche Wert true.
260 : *
261 : * @access public
262 : * @param array $data Assoziatives Array mit den neuen Werten
263 : * @return mixed String mit Fehlermeldungen oder true bei Erfolg
264 : */
265 : function setData($data) {
266 0 : $errors = "";
267 0 : if (($result = $this->validateName($data["name"])) !== true) {
268 0 : $errors.= $result."\n";
269 0 : }
270 0 : if (($result = $this->validateLeaderID($data["leader"])) !== true) {
271 0 : $errors.= $result."\n";
272 0 : }
273 0 : if (($result = $this->validateTemplateFolder(isset($data["folder"]) ? $data["folder"] : "")) !== true) {
274 0 : $errors.= $result."\n";
275 0 : }
276 0 : if (($result = $this->validateDeadline(mktime($data["deadline_hour"], $data["deadline_minute"], 0, $data["deadline_month"], $data["deadline_day"], $data["deadline_year"]))) !== true) {
277 0 : $errors.= $result."\n";
278 0 : }
279 0 : if (empty($errors)) {
280 0 : if (!$this->setName($data["name"])) {
281 0 : return "Name konnte nicht gespeichert werden.";
282 : }
283 0 : if (!$this->setDescription($data["description"])) {
284 0 : return "Beschreibung konnte nicht gespeichert werden.";
285 : }
286 0 : if (!$this->setLeaderID($data["leader"])) {
287 0 : return "Spielleiter konnte nicht gespeichert werden.";
288 : }
289 0 : if (!$this->setTemplateFolder($data["folder"])) {
290 0 : return "Template-Ordner konnte nicht gespeichert werden.";
291 : }
292 0 : if (isset($data["createfolder"]) && !$this->createRessourceFolder()) {
293 0 : return "Ressourcen-Ordner konnte nicht erstellt werden.";
294 : }
295 0 : if (isset($data["createboard"]) && !$this->createBoard()) {
296 0 : return "Board konnte nicht erstellt werden.";
297 : }
298 0 : if (!$this->setFinished(isset($data["finished"]))) {
299 0 : return "Planspielabschluss konnte nicht gespeichert werden.";
300 : }
301 0 : if (!$this->setDeadline(mktime($data["deadline_hour"], $data["deadline_minute"], 0, $data["deadline_month"], $data["deadline_day"], $data["deadline_year"]))) {
302 0 : return "Deadline konnte nicht gespeichert werden.";
303 : }
304 0 : if (isset($data["inProgress_hour"]) && !$this->setInProgressSince(mktime($data["inProgress_hour"], $data["inProgress_minute"], 0, $data["inProgress_month"], $data["inProgress_day"], $data["inProgress_year"]))) {
305 0 : return "Startdatum konnte nicht gespeichert werden.";
306 : }
307 0 : return true;
308 : }
309 0 : return trim($errors);
310 : }
311 : /**
312 : * Erstellt den grundlegenden Datenbankeintrag für das Planspiel. Gesetzt wird
313 : * nur die Kurs-ID, die anderen Felder werden mit ihren Standardwerten belegt.
314 : *
315 : * @access private
316 : * @return boolean Erfolgswert
317 : */
318 : function createPlanspiel() {
319 0 : global $db, $settings;
320 0 : $dbp = $settings["dbPrefix"];
321 0 : $db->query("INSERT INTO {$dbp}planspiel (course_id) VALUES ('$this->courseID')");
322 0 : if ($db->rows_affected) {
323 0 : $this->ID = $db->insert_id;
324 0 : return true;
325 : }
326 0 : return false;
327 : }
328 : /**
329 : * Löscht dieses Planspiel und die zugehörigen Phasen.
330 : *
331 : * @access public
332 : * @return boolean Erfolgswert
333 : */
334 : function deletePlanspiel() {
335 0 : global $db, $settings, $EZSQL_ERROR;
336 0 : $dbp = $settings["dbPrefix"];
337 0 : $errorCount = count($EZSQL_ERROR);
338 0 : $db->query("DELETE FROM {$dbp}planspiel WHERE id='$this->ID'");
339 0 : foreach($this->getPhases() as $phase) {
340 0 : $phase->deletePhase();
341 0 : }
342 0 : if (count($EZSQL_ERROR) > $errorCount) {
343 0 : return false;
344 : }
345 0 : $this->setDefaultValues();
346 0 : return true;
347 : }
348 : /**
349 : * Gibt zurück, ob eine übergebene Phase eine Phase dieses Planspiels ist.
350 : *
351 : * @access public
352 : * @param int $phaseID ID der Phase
353 : * @return boolean true, wenn die Phase zu diesem Planspiel gehört, sonst false
354 : */
355 : function phaseInPlanspiel($phaseID) {
356 0 : if (strval(intval($phaseID)) != $phaseID || $phaseID < 0) {
357 0 : return false;
358 : }
359 0 : if ($phaseID == 0) {
360 0 : return true;
361 : }
362 0 : foreach($this->getPhases() as $phase) {
363 0 : if ($phase->getID() == $phaseID) {
364 0 : return true;
365 : }
366 0 : }
367 0 : return false;
368 : }
369 : /**
370 : * Listet alle Phasen dieses Planspiels auf.
371 : *
372 : * @access public
373 : * @return void
374 : */
375 : function listPhases() {
376 0 : global $db, $settings;
377 0 : $dbp = $settings["dbPrefix"];
378 0 : $admin = $_SESSION["usergroup"] == ADMIN || ($_SESSION["usergroup"] == DOZENT && $this->courseID > 0);
379 0 : $phases = $this->getPhases();
380 0 : if (!empty($phases)) {
381 0 : $planspielRoles = PlanspielList::getPlanspielRoleIDs($this->courseID);
382 0 : echo "<table class='contentTable'>\n";
383 0 : Output::echoTableHead("Phasen im Planspiel »".Data::toHTML($this->name, false) ."«", 7);
384 0 : echo "<tr><th>Name</th><th>Verantwortlicher</th><th>Abgeschlossen</th><th>Aufwand</th><th></th><th>Budget</th></tr>";
385 0 : foreach($phases as $phase) {
386 0 : $ID = $phase->getID();
387 0 : echo "<tr valign='top'>";
388 0 : echo "<td><a href='".PATH_TO_ROOT."planspiel/document.php?phaseID=".$phase->getID() ."&planspielID=$this->ID' title='Dokumente anzeigen'>";"</a><br />";
389 :
390 0 : if ($phase->isCurrent() == TRUE){
391 0 : echo "<b><i>".Data::toHTML($phase->getName(), false) ."</i></b>";
392 0 : } else {
393 0 : echo "<b>".Data::toHTML($phase->getName(), false) ."</b>";
394 : }
395 0 : echo "</a>";
396 0 : if ( $phase->isMilestone() == "1"){
397 0 : echo "<br />(Meilenstein)";
398 0 : }
399 0 : echo "<br /><a href='phasedetails.php?ID=".$phase->getID() ."&tab=1' title='Details anzeigen'"."><img src='".PATH_TO_ROOT."images/icon_planspiel_statistics.gif' alt= 'Statistik anzeigen' /> Details</a></td>";
400 0 : echo "<td>".$phase->getResponsibleUser() ."</td>";
401 0 : echo "<td><a href='".PATH_TO_ROOT."planspiel/document.php?phaseID=".$phase->getID() ."&planspielID=$this->ID' title='Dokumente bearbeiten'>".$phase->getFinishedDocumentsCount() ."/".count($phase->getDocuments()) ." Dokumente</a><br />";
402 :
403 0 : if ( $phase->getDocumentsCount() == 0 ){
404 0 : $status = "0";
405 0 : } else {
406 0 : $status = ($phase->getFinishedDocumentsCount() *100 / $phase->getDocumentsCount());
407 : }
408 0 : echo "Fortschritt: <b>".number_format($status,0)."%</b><br />";
409 0 : $deadline = intval($db->get_var("SELECT deadline FROM {$dbp}planspiel_phase WHERE ID='$ID'"));
410 0 : if($deadline == "0"){
411 0 : echo "DL: n.d."."</td>";
412 0 : } else {
413 0 : echo "DL: ".date("d.m.Y H:i", $deadline);
414 : }
415 0 : echo "</td><td>";
416 0 : echo "A: ".$phase->getEstimatedEffort() ."<br />";
417 0 : echo "B: ".$phase->getDaysSpent() ."<br />";
418 0 : echo "C: ".$phase->getETC();
419 0 : echo "</td>";
420 : //Budget Balken
421 0 : if($phase->getEstimatedEffort() == 0){
422 0 : $colors = new ColorIndicator("100", "0");
423 0 : } else {
424 0 : $colors = new ColorIndicator("100", (($phase->getDaysSpent())+($phase->getETC()))*100/($phase->getEstimatedEffort()));
425 : }
426 0 : $colors->is_budget();
427 : ?> <td><table border="1" cellpadding="0" style= " height: 35px; border-collapse: collapse; border-color: #000000; width: 10px;" >
428 : <tr>
429 0 : <td title="<?php echo $colors->tooltip; ?>" style=" background-color:<?php echo $colors->budget_color; ?>;"> </td>
430 : </tr>
431 : </table></td>
432 0 : <?php
433 :
434 0 : echo "<td>";
435 0 : if ($admin || (isset($_SESSION["roleID"]) && (($_SESSION["roleID"] == $planspielRoles["leader"] && $_SESSION["userid"] == $this->leaderID) || ($_SESSION["roleID"] == $planspielRoles["phaseResponsible"] && $_SESSION["userid"] == $phase->getResponsibleUserID())))) {
436 0 : echo "<a href='".PATH_TO_ROOT.SCRIPT_NAME."?action=editPhase&phaseID=".$phase->getID() ."&ID=$this->ID'>".Output::getIcon("icon_edit", "Bearbeiten") ."</a>";
437 0 : }
438 0 : if ($admin || (isset($_SESSION["roleID"]) && $_SESSION["roleID"] == $planspielRoles["leader"] && $_SESSION["userid"] == $this->leaderID)) {
439 0 : echo "<a href='".PATH_TO_ROOT.SCRIPT_NAME."?action=deletePhase&phaseID=".$phase->getID() ."&ID=$this->ID'>".Output::getIcon("icon_muell", "Löschen") ."</a>";
440 0 : if (count($phases) > 1) {
441 0 : echo "<a href='".PATH_TO_ROOT.SCRIPT_NAME."?action=switchPhase&phaseID=".$phase->getID() ."&ID=$this->ID'>".Output::getIcon("icon_moduleswitch", "Phasenreihenfolge ändern") ."</a>";
442 0 : }
443 0 : }
444 0 : echo "</td></tr>";
445 0 : }
446 0 : echo "</table>";
447 0 : echo "<p>A: Geschätzter Aufwand<br/>B: Aufgewendete Zeit<br/>C: Geschätzte Zeit bis zum Abschluss<br/>(alle Angaben in Personentagen)<br />DL: Deadline<br />n.d.: nicht definiert<br /><i>kursiv</i>: aktuelle Phase</p>";
448 :
449 0 : } else {
450 0 : echo "<p>Es wurden noch keine Phasen angelegt.</p>";
451 : }
452 0 : }
453 : /**
454 : * Zeigt das Formular zum Ändern der Phasenreihenfolge an.
455 : *
456 : * @access public
457 : * @return void
458 : */
459 : function showPhaseSwitchForm($phaseID) {
460 0 : $phases = $this->getPhases();
461 0 : if (!empty($phases)) {
462 0 : $form = new Formular();
463 0 : $form->setTemplate("<table class='tableBorder'>", "<tr valign='top'><td>", "<td>");
464 0 : $form->setButtons(2, "Speichern");
465 0 : $form->addRawCode("<tr><td colspan='2' class='tableHead'>Phasenreihenfolge</td></tr>");
466 0 : $form->addInput("hidden", "ID", "", 0, $this->ID);
467 0 : $form->addInput("hidden", "phaseID", "", 0, $phaseID);
468 0 : $data = array();
469 0 : $data[] = array("An erster Stelle", 1);
470 0 : $phaseOrder = 0;
471 0 : foreach($phases as $phase) {
472 0 : if ($phase->getID() == $phaseID) {
473 0 : $phaseOrder = $phase->getOrder();
474 0 : } else {
475 0 : $data[] = array("Nach ".Data::toHTML($phase->getName(), false), $phase->getOrder() +1);
476 : }
477 0 : }
478 0 : $form->addSelect("order", "Anordnung", $data, 1, false, $phaseOrder);
479 0 : $form->addButtons();
480 0 : echo $form->getForm();
481 0 : } else {
482 : "<p>Es wurden noch keine Phasen angelegt.</p>";
483 : }
484 0 : }
485 : /**
486 : * Überprüft den übergebenen Namen auf Gültigkeit.
487 : *
488 : * @access public
489 : * @param string $name Der zu überprüfende String
490 : * @return mixed String mit Fehlerangabe oder true bei Erfolg
491 : */
492 : function validateName($name) {
493 0 : global $db, $settings;
494 0 : $dbp = $settings["dbPrefix"];
495 0 : $name = trim(Data::gpcUnescape($name));
496 0 : if (empty($name)) {
497 0 : return "Der Name wurde nicht angegeben.";
498 : }
499 0 : if (strlen($name) > 100) {
500 0 : return "Der Name ist zu lang.";
501 : }
502 0 : if ($this->ID == 0 && $db->get_var("SELECT COUNT(*) FROM {$dbp}planspiel WHERE course_id='$this->courseID' AND name='".Data::toMysql($name, false) ."'")) {
503 0 : return "Der Name ist in diesem Kurs bereits vergeben.";
504 : }
505 0 : return true;
506 : }
507 :
508 : function validateDeadline($deadline) {
509 0 : if ($this->deadline == $deadline) {
510 0 : return true;
511 : }
512 :
513 0 : $date = getdate(time());
514 0 : $tomorrow = mktime(23, 59, 59, $date["mon"], $date["mday"], $date["year"]);
515 0 : if ($deadline < $tomorrow) {
516 0 : return "Die Deadline muss mindestens einen Tag in der Zukunft liegen.";
517 : }
518 0 : return true;
519 : }
520 :
521 : /**
522 : * Überprüft die übergebene Spielleiter-ID auf Gültigkeit.
523 : *
524 : * @access public
525 : * @param int $leaderID Die zu überprüfende ID
526 : * @return mixed String mit Fehlerangabe oder true bei Erfolg
527 : */
528 : function validateLeaderID($leaderID) {
529 0 : global $db, $settings;
530 0 : $dbp = $settings["dbPrefix"];
531 0 : $users = $db->get_col("SELECT userID FROM {$dbp}user_course WHERE courseID='$this->courseID'");
532 0 : if (!in_array($leaderID, $users)) {
533 0 : return "Die Angabe des Spielleiters ist ungültig.";
534 : }
535 0 : return true;
536 : }
537 : /**
538 : * Überprüft die übergebene Verzeichnis-ID auf Gültigkeit.
539 : *
540 : * @access public
541 : * @param int $folderID Die zu überprüfende ID
542 : * @return mixed String mit Fehlerangabe oder true bei Erfolg
543 : */
544 : function validateTemplateFolder($folderID) {
545 0 : global $db, $settings;
546 0 : $dbp = $settings["dbPrefix"];
547 0 : if (empty($folderID)) {
548 0 : return "Template-Ordner nicht ausgewählt.";
549 : }
550 0 : $folders = $db->get_col("SELECT fileID FROM {$dbp}filelist WHERE type='folder' AND courseID='$this->courseID'");
551 0 : if (!in_array($folderID, $folders)) {
552 0 : return "Template-Ordner ungültig.";
553 : }
554 0 : return true;
555 : }
556 : /**
557 : * Speichert den übergebenen String als neuen Namen dieses Planspiels.
558 : * Der String sollte vorher mit der Methode validateName() validiert worden
559 : * sein!
560 : *
561 : * @access public
562 : * @param string $name Zu speichernder Name
563 : * @return boolean Erfolgswert
564 : */
565 : function setName($name) {
566 0 : global $db, $settings;
567 0 : $dbp = $settings["dbPrefix"];
568 0 : $name = trim($name);
569 0 : if ($this->name == Data::gpcUnescape($name)) {
570 0 : return true;
571 : }
572 0 : if ($this->ID == 0) {
573 0 : if (!$this->createPlanspiel()) {
574 0 : return false;
575 : }
576 0 : }
577 0 : $db->query("UPDATE {$dbp}planspiel SET name='".Data::toMysql($name) ."' WHERE id='$this->ID'");
578 0 : if ($db->rows_affected) {
579 0 : $this->name = Data::gpcUnescape($name);
580 0 : if ($this->folderID > 0) {
581 0 : $db->query("UPDATE {$dbp}filelist SET name='Planspiel: ".Data::toMysql($this->name, false) ."', link='".Data::toMysql($this->name, false) ."' WHERE fileID='$this->folderID'");
582 0 : }
583 0 : if ($this->boardID > 0) {
584 0 : $db->query("UPDATE {$dbp}forum_board SET boardname='".Data::toMysql($this->name, false) ."', boarddescription='".Data::toMysql("Board zum Planspiel »{$this->name}«", false) ."' WHERE boardid='$this->boardID'");
585 0 : }
586 0 : return true;
587 : }
588 0 : return false;
589 : }
590 :
591 : function setDeadline($deadline) {
592 0 : global $db, $settings;
593 0 : $dbp = $settings["dbPrefix"];
594 :
595 0 : if ($this->deadline == $deadline) {
596 0 : return true;
597 : }
598 0 : $db->query("UPDATE {$dbp}planspiel SET deadline='$deadline' WHERE id='$this->ID'");
599 0 : if ($db->rows_affected) {
600 0 : $this->deadline = $deadline;
601 0 : return true;
602 : }
603 0 : return false;
604 : }
605 :
606 : /**
607 : * Speichert den übergebenen String als neue Beschreibung dieses Planspiels.
608 : *
609 : * @access public
610 : * @param string $desc Zu speichernde Beschreibung
611 : * @return boolean Erfolgswert
612 : */
613 : function setDescription($desc) {
614 0 : global $db, $settings;
615 0 : $dbp = $settings["dbPrefix"];
616 0 : $desc = trim($desc);
617 0 : if ($this->description == Data::gpcUnescape($desc)) {
618 0 : return true;
619 : }
620 0 : if ($this->ID == 0) {
621 0 : if (!$this->createPlanspiel()) {
622 0 : return false;
623 : }
624 0 : }
625 0 : if (empty($desc)) {
626 0 : $descSQL = "NULL";
627 0 : } else {
628 0 : $descSQL = "'".Data::toMysql($desc) ."'";
629 : }
630 0 : $db->query("UPDATE {$dbp}planspiel SET description=$descSQL WHERE id='$this->ID'");
631 0 : if ($db->rows_affected) {
632 0 : $this->description = Data::gpcUnescape($desc);
633 0 : return true;
634 : }
635 0 : return false;
636 : }
637 : /**
638 : * Speichert die übergebene ID als neuen Spielleiter dieses Planspiels.
639 : * Die ID sollte vorher mit der Methode validateLeaderID() validiert worden sein!
640 : *
641 : * @access public
642 : * @param int $leaderID Zu speichernde Spielleiter-ID
643 : * @return boolean Erfolgswert
644 : */
645 : function setLeaderID($leaderID) {
646 0 : global $db, $settings;
647 0 : $dbp = $settings["dbPrefix"];
648 0 : $leaderID = trim($leaderID);
649 0 : if ($this->leaderID == Data::gpcUnescape($leaderID)) {
650 0 : return true;
651 : }
652 0 : if ($this->ID == 0) {
653 0 : if (!$this->createPlanspiel()) {
654 0 : return false;
655 : }
656 0 : }
657 0 : $db->query("UPDATE {$dbp}planspiel SET leader='".Data::toMysql($leaderID) ."' WHERE id='$this->ID'");
658 0 : if ($db->rows_affected) {
659 0 : $newLeaderID = intval(Data::gpcUnescape($leaderID));
660 0 : $roles = PlanspielList::getPlanspielRoleIDs($this->courseID);
661 0 : $urm = new UserRoleManagement($this->courseID);
662 0 : if (count(PlanspielList::getPlanspielWhereLeader($this->courseID, $this->leaderID)) == 0) {
663 0 : $urm->unsetRoleForUser($this->leaderID, $roles["leader"]);
664 0 : }
665 0 : $urm->setRoleForUser($newLeaderID, $roles["leader"]);
666 0 : $this->leaderID = $newLeaderID;
667 0 : return true;
668 : }
669 0 : return false;
670 : }
671 : /**
672 : * Speichert, ob dieses Planspiels abgeschlossen ist.
673 : *
674 : * @access public
675 : * @param bool $finished Abgeschlossen oder nicht
676 : * @return boolean Erfolgswert
677 : */
678 : function setFinished($finished) {
679 0 : global $db, $settings;
680 0 : $dbp = $settings["dbPrefix"];
681 0 : $finished = (bool)$finished;
682 0 : if ($this->isFinished == $finished) {
683 0 : return true;
684 : }
685 0 : if ($this->ID == 0) {
686 0 : if (!$this->createPlanspiel()) {
687 0 : return false;
688 : }
689 0 : }
690 0 : $db->query("UPDATE {$dbp}planspiel SET finished='".intval($finished) ."' WHERE id='$this->ID'");
691 0 : if ($db->rows_affected) {
692 0 : $this->isFinished = $finished;
693 0 : return true;
694 : }
695 0 : return false;
696 : }
697 : /**
698 : * Speichert die übergebene ID als neuen Template-Ordner dieses Planspiels.
699 : * Die ID sollte vorher mit der Methode validateTemplateFolder() validiert worden sein!
700 : *
701 : * @access public
702 : * @param int $folderID Zu speichernde Verzeichnis-ID
703 : * @return boolean Erfolgswert
704 : */
705 : function setTemplateFolder($folderID) {
706 0 : global $db, $settings;
707 0 : $dbp = $settings["dbPrefix"];
708 0 : $folderID = trim($folderID);
709 0 : if ($this->templateFolder == Data::gpcUnescape($folderID)) {
710 0 : return true;
711 : }
712 0 : if ($this->ID == 0) {
713 0 : if (!$this->createPlanspiel()) {
714 0 : return false;
715 : }
716 0 : }
717 0 : $db->query("UPDATE {$dbp}planspiel SET template_folder='".Data::toMysql($folderID) ."' WHERE id='$this->ID'");
718 0 : if ($db->rows_affected) {
719 0 : $this->templateFolder = intval(Data::gpcUnescape($folderID));
720 0 : return true;
721 : }
722 0 : return false;
723 : }
724 : /**
725 : * Speichert die neue Reihenfolge der Phasen.
726 : *
727 : * @access public
728 : * @param int $phaseID ID der Phase, für die eine neue Position festgelegt wurde
729 : * @param int $order Neue Position der Phase
730 : * @return boolean Erfolgswert
731 : */
732 : function setPhaseOrder($phaseID, $order) {
733 0 : $phases = $this->getPhases();
734 0 : if (!$this->phaseInPlanspiel($phaseID) || strval(intval($order)) != $order || $order < 1 || $order > count($phases) +1) {
735 0 : return false;
736 : }
737 0 : foreach($phases as $phase) {
738 0 : if ($phase->getID() == $phaseID) {
739 0 : $oldOrder = $phase->getOrder();
740 0 : break;
741 : }
742 0 : }
743 0 : if ($oldOrder == $order) {
744 0 : return true;
745 : }
746 0 : foreach($phases as $phase) {
747 0 : $phaseOrder = $phase->getOrder();
748 0 : if ($oldOrder > $order && $phaseOrder < $oldOrder && $phaseOrder >= $order) {
749 0 : $phase->setOrder($phaseOrder+1);
750 0 : } elseif ($oldOrder < $order && $phaseOrder > $oldOrder && $phaseOrder <= $order) {
751 0 : $phase->setOrder($phaseOrder-1);
752 0 : }
753 0 : if ($phase->getID() == $phaseID) {
754 0 : if ($oldOrder < $order) $order--;
755 0 : $phase->setOrder($order);
756 0 : }
757 0 : }
758 0 : return true;
759 : }
760 :
761 : function setInProgressSince($in_progressSince){
762 0 : global $db, $settings;
763 0 : $dbp = $settings["dbPrefix"];
764 :
765 0 : if($this->in_progress == $in_progressSince){
766 0 : return true;
767 : }
768 0 : $db->query("UPDATE {$dbp}planspiel SET in_progress='$in_progressSince' WHERE id='$this->ID'");
769 0 : if ($db->rows_affected) {
770 0 : $this->in_progress = $in_progressSince;
771 0 : return true;
772 : }
773 0 : return false;
774 : }
775 :
776 : /**
777 : * Erstellt den Ressourcen-Ordner für dieses Planspiel.
778 : *
779 : * @access public
780 : * @return boolean Erfolgswert
781 : */
782 : function createRessourceFolder() {
783 0 : global $db, $settings;
784 0 : $dbp = $settings["dbPrefix"];
785 0 : if (empty($this->name)) {
786 0 : return false;
787 : }
788 0 : $insert = new Insert();
789 0 : $data = array("link" => $this->name, "name" => "Planspiel: ".$this->name, "size" => 0, "userID" => $_SESSION["userid"], "create_time" => time(), "courseID" => $this->courseID, "description" => "", "type" => "ROOT", "visible_type" => 1, // Sichtbarkeit: Alle
790 0 : "start_time" => 0, "end_time" => 2147483647, "parent_object" => 0, "student_write" => 0, "orig_filename" => "", "extension" => "", "tmpemail" => false, "tmpteacherEMail" => false,);
791 0 : ob_start();
792 0 : $fileID = $insert->resolveForm($data);
793 0 : ob_end_clean();
794 0 : if ($fileID) {
795 0 : $db->query("UPDATE {$dbp}planspiel SET folder_id='$fileID' WHERE id='$this->ID'");
796 0 : if ($db->rows_affected) {
797 0 : $this->folderID = intval($fileID);
798 0 : return true;
799 : }
800 0 : }
801 0 : return false;
802 : }
803 : /**
804 : * Erstellt das Board für dieses Planspiel.
805 : *
806 : * @access public
807 : * @return boolean Erfolgswert
808 : */
809 : function createBoard() {
810 0 : global $db, $settings, $EZSQL_ERROR;
811 : // kein require_once, sonst Konflikte mit dem Forum (Redeklaration von Funktionen)
812 0 : include_once (PATH_TO_ROOT."forum/admin/classes/class.adminfunctions.inc.php");
813 0 : $dbp = $settings["dbPrefix"];
814 0 : if (empty($this->name)) {
815 0 : return false;
816 : }
817 0 : $errorCount = count($EZSQL_ERROR);
818 0 : $order = intval($db->get_var("SELECT MAX(boardorder) FROM {$dbp}forum_board WHERE categoryid='$this->courseID'")) +1;
819 0 : $sql = "INSERT INTO {$dbp}forum_board (boardname, boarddescription, categoryid, boardorder, boarddisabled, anonymousallowed, filesallowed, helpdesk) "."VALUES ('".Data::toMysql($this->name, false) ."', '".Data::toMysql("Board zum Planspiel »{$this->name}«", false) ."', '$this->courseID', '$order', 0, 0, 1, 0)";
820 0 : $db->query($sql);
821 0 : if (count($EZSQL_ERROR) == $errorCount) {
822 0 : $boardID = $db->insert_id;
823 0 : addBoardRights($this->courseID, $boardID, "111000010000000000", "100000000000000000");
824 0 : $this->boardID = $boardID;
825 0 : $db->query("UPDATE {$dbp}planspiel SET board_id='$boardID' WHERE id='$this->ID'");
826 0 : return true;
827 : }
828 0 : return false;
829 : }
830 : /**
831 : * Gibt die ID dieses Planspiels zurück.
832 : *
833 : * @access public
834 : * @return int ID des Planspiels
835 : */
836 : function getID() {
837 0 : return $this->ID;
838 : }
839 : /**
840 : * Gibt die Kurs-ID dieses Planspiels zurück.
841 : *
842 : * @access public
843 : * @return int ID des Kurses, zu dem das Planspiel gehört
844 : */
845 : function getCourseID() {
846 0 : return $this->courseID;
847 : }
848 : /**
849 : * Gibt die ID des Spielleiters dieses Planspiels zurück.
850 : *
851 : * @access public
852 : * @return int ID des Spielleiters
853 : */
854 : function getLeaderID() {
855 0 : return $this->leaderID;
856 : }
857 : /**
858 : * Gibt den Namen, Rolle und Teamzugehörigkeit des Spielleiters dieses Planspiels zurück.
859 : * Der Name ist verlinkt auf das Profil des Benutzers, die Rolle auf deren Eigenschaftenseite.
860 : *
861 : * @access public
862 : * @return string HTML-String mit Angaben zum Spielleiter
863 : */
864 : function getLeader() {
865 0 : global $db, $settings;
866 0 : $dbp = $settings["dbPrefix"];
867 0 : $urm = new UserRoleManagement($this->courseID);
868 0 : $utm = new UserTeamManagement($this->courseID);
869 0 : $leader = "<a href='".PATH_TO_ROOT."user/homepage.php?user=$this->leaderID'>".Data::toHTML($db->get_var("SELECT CONCAT(Nachname, ', ', Vorname) FROM {$dbp}user WHERE ID='$this->leaderID'"), false) ."</a>";
870 0 : $team = $utm->getTeamOfUser($this->leaderID);
871 0 : return $leader;
872 : }
873 : /**
874 : * Gibt den Namen dieses Planspiels zurück.
875 : *
876 : * @access public
877 : * @return string Name des Planspiels
878 : */
879 : function getName() {
880 0 : return $this->name;
881 : }
882 : /**
883 : * Gibt die Beschreibung dieses Planspiels zurück.
884 : *
885 : * @access public
886 : * @param boolean $bbcode Gibt an, ob BBCode in der Beschreibung bereits umgewandelt werden soll.
887 : * @return string Beschreibung des Planspiels
888 : */
889 : function getDescription($bbcode = true) {
890 0 : if ($bbcode) {
891 0 : $bb = new BBCode();
892 0 : return $bb->parse($this->description);
893 : }
894 0 : return $this->description;
895 : }
896 : /**
897 : * Gibt die Phasen-Objekte dieses Planspiels zurück.
898 : *
899 : * @access public
900 : * @return array Phasen-Objekte des Planspiels
901 : */
902 : function getPhases() {
903 0 : global $db, $settings;
904 0 : $dbp = $settings["dbPrefix"];
905 0 : if (!isset($this->phases)) {
906 0 : $this->phases = array();
907 0 : $phases = $db->get_col("SELECT id FROM {$dbp}planspiel_phase WHERE planspiel_id='$this->ID' ORDER BY phase_order");
908 0 : if ($db->num_rows) foreach($phases as $phase) {
909 0 : $this->phases[] = new Phase($phase);
910 0 : }
911 0 : }
912 0 : return $this->phases;
913 : }
914 : /**
915 : * Gibt die aktuell in Bearbeitung befindliche Phase des Planspiels zurück.
916 : * Sind noch keine Phase definiert oder schon alle Phasen abgeschlossen, wird false zurückgegeben.
917 : *
918 : * @access public
919 : * @return mixed Phasen-Objekt der aktuellen Phase oder false
920 : */
921 : function getCurrentPhase() {
922 0 : foreach($this->getPhases() as $phase) {
923 0 : if (!$phase->isFinished()) {
924 0 : return $phase;
925 : }
926 0 : }
927 0 : return false;
928 : }
929 : /**
930 : * Gibt die ID des Template-Ordners dieses Planspiels zurück.
931 : *
932 : * @access public
933 : * @return int Template-Ordner des Planspiels
934 : */
935 : function getTemplateFolder() {
936 0 : return $this->templateFolder;
937 : }
938 : /**
939 : * Gibt einen Link zum Neuanlegen einer Phase zurück.
940 : *
941 : * @access public
942 : * @return string Link zum Anlegen einer neuen Phase
943 : */
944 : function getNewPhaseLink() {
945 0 : return "<p><a href='".PATH_TO_ROOT.SCRIPT_NAME."?action=editPhase&phaseID=0&ID=$this->ID'>Neue Phase anlegen</a></p>";
946 : }
947 : /**
948 : * Gibt zurück, ob das Planspiel abgeschlossen ist.
949 : *
950 : * @access public
951 : * @return bool Planspiel abgeschlossen oder nicht
952 : */
953 : function isFinished() {
954 0 : return $this->isFinished;
955 : }
956 : /**
957 : * Gibt die Anzahl der bereits abgeschlossenen Phasen dieses Planspiels zurück.
958 : *
959 : * @access public
960 : * @return int Anzahl der abgeschlossenen Phasen
961 : */
962 : function getFinishedPhasesCount() {
963 0 : $finished = 0;
964 0 : foreach($this->getPhases() as $phase) {
965 0 : if ($phase->isFinished()) {
966 0 : $finished++;
967 0 : }
968 0 : }
969 0 : return $finished;
970 : }
971 : /**
972 : * Gibt die Anzahl der Phasen dieses Planspiels zurück.
973 : *
974 : * @access public
975 : * @return int Anzahl der Phasen
976 : */
977 : function getPhasesCount() {
978 0 : return count($this->getPhases());
979 : }
980 : /**
981 : * Gibt die ID der Planspiel-Map zurück, die mit diesem Planspiel verknüpft wurde.
982 : * Ist keine vorhanden, wird false zurückgegeben.
983 : *
984 : * @access public
985 : * @return mixed Map-ID, falls vorhanden, sonst false
986 : */
987 : function getMapID() {
988 0 : global $db, $settings;
989 0 : $dbp = $settings["dbPrefix"];
990 0 : if (!isset($this->mapID)) {
991 0 : $this->mapID = intval($db->get_var("SELECT map_id FROM {$dbp}mapdesigner_planspiel WHERE planspiel_id='$this->ID'"));
992 0 : }
993 0 : if ($this->mapID > 0) {
994 0 : return $this->mapID;
995 : } else {
996 0 : return false;
997 : }
998 : }
999 :
1000 : /**
1001 : * Gibt einen auf die Map verlinkten img-Tag zurück, der die Map als Thumbnail zeigt oder false, falls keine Map vorhanden.
1002 : *
1003 : * @access public
1004 : * @param int $width Breite
1005 : * @param int $height Höhe
1006 : * @return mixed string mit HTML-Tag oder false
1007 : */
1008 : function getMapThumbnail($width = 120, $height = 90) {
1009 0 : global $db, $settings;
1010 0 : $dbp = $settings["dbPrefix"];
1011 0 : $mapID = $this->getMapID();
1012 0 : if ($mapID) {
1013 0 : $map = $db->get_row("SELECT * FROM {$dbp}mapdesigner_map WHERE map_id='$mapID'");
1014 0 : if (!is_null($map)) {
1015 0 : $pic = PATH_TO_ROOT.$settings["upload_path"].'mapdesigner/'.$map->course_id.'/'.$map->image;
1016 0 : return "<a href='".PATH_TO_ROOT."mapdesigner/showmap.php?map=$mapID'><img src='".PATH_TO_ROOT."common/makethumb.php?picurl=".rawurlencode($pic)."&maxh=$height&maxw=$width' alt='Planspiel-Map'/></a>";
1017 : }
1018 0 : }
1019 0 : return false;
1020 : }
1021 :
1022 : /**
1023 : * Gibt einen Link auf die Planspielmap (falls vorhanden) oder die Phasenübersicht zurück.
1024 : *
1025 : * @access public
1026 : * @param bool $map Soll auf die Planspiel-Map verlinkt werden, wenn eine existiert?
1027 : * @return string Verlinkter Planspielname
1028 : */
1029 : function getLink($map = true) {
1030 0 : if ($map && ($mapID = $this->getMapID())) {
1031 0 : return "<a href='".PATH_TO_ROOT."mapdesigner/showmap.php?map=$mapID' title='Zur Planspielmap'>".Data::toHTML($this->name, false) ."</a>";
1032 : }
1033 0 : return "<a href='".PATH_TO_ROOT."planspiel/planspiel.php?action=showPhases&ID=".$this->ID."' title='Zur Phasenübersicht'>".Data::toHTML($this->name, false) ."</a>";
1034 : }
1035 : /**
1036 : * Gibt den geschätzten Aufwand in PT zurück.
1037 : *
1038 : * @access public
1039 : * @return float Personentage
1040 : */
1041 : function getEstimatedEffort() {
1042 0 : $sum = 0;
1043 0 : foreach($this->getPhases() as $phase) {
1044 0 : $sum+= $phase->getEstimatedEffort();
1045 0 : }
1046 :
1047 0 : return $sum;
1048 : }
1049 : /**
1050 : * Gibt die bisher aufgewendeten PT zurück.
1051 : *
1052 : * @access public
1053 : * @return float Personentage
1054 : */
1055 : function getDaysSpent() {
1056 0 : $sum = 0;
1057 0 : foreach($this->getPhases() as $phase) {
1058 0 : $sum += $phase->getDaysSpent();
1059 0 : }
1060 :
1061 : // Ermittle und addiere die Aufwände des Spielleiters
1062 0 : $this->planspielBudget = new PlanspielBudget($this->ID);
1063 0 : $sum += $this->planspielBudget->GetSpielleiterBudget();
1064 :
1065 0 : return $sum;
1066 : }
1067 : /**
1068 : * Gibt die ETC in PT zurück.
1069 : *
1070 : * @access public
1071 : * @return float Personentage
1072 : */
1073 : function getETC() {
1074 0 : $sum = 0;
1075 0 : foreach($this->getPhases() as $phase) {
1076 0 : $sum+= $phase->getETC();
1077 0 : }
1078 0 : return $sum;
1079 : }
1080 : }
1081 : ?>
|